using System.Diagnostics;
using System.Text.Json;
using Newtonsoft.Json;
using SPI.AgentServer.Models;
using SPI.AgentServer.Services.AI;
using SPI.AgentServer.Services.Tools;
using SPI.AgentServer.Services.Export;
using SPI.AgentServer.Services.Cache;
using IChartService = SPI.AgentServer.Services.Export.IChartService;

namespace SPI.AgentServer.Services.Orchestration;

/// <summary>
/// 查询编排器 - 整个查询处理流程的核心协调者
/// 负责：
/// 1. 接收自然语言查询
/// 2. 调用 AI 模型理解意图
/// 3. 执行相应的工具或 SQL
/// 4. 整合结果并生成摘要
/// </summary>
public class QueryOrchestrator : IQueryOrchestrator
{
    private readonly IQwenClient _qwenClient;
    private readonly IPromptManager _promptManager;
    private readonly IToolExecutor _toolExecutor;
    private readonly IChartService _chartService;
    private readonly IQueryCacheService _cacheService;
    private readonly ILogger<QueryOrchestrator> _logger;
    private readonly IConfiguration _configuration;
    // 最大重试次数，当查询失败时会尝试重新处理（降低重试避免超时）
    private const int MaxRetryAttempts = 2;
    // 数据量阈值，超过此值时提供导出链接
    private const int ExportThreshold = 20;

    public QueryOrchestrator(
        IQwenClient qwenClient,
        IPromptManager promptManager,
        IToolExecutor toolExecutor,
        IChartService chartService,
        IQueryCacheService cacheService,
        IConfiguration configuration,
        ILogger<QueryOrchestrator> logger)
    {
        _qwenClient = qwenClient;
        _promptManager = promptManager;
        _toolExecutor = toolExecutor;
        _chartService = chartService;
        _cacheService = cacheService;
        _configuration = configuration;
        _logger = logger;
    }

    /// <summary>
    /// 处理用户的查询请求
    /// 这是整个服务的主要入口点
    /// </summary>
    /// <param name="request">包含自然语言查询和上下文信息的请求对象</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>包含查询结果、摘要和元数据的响应对象</returns>
    public async Task<QueryResponse> ProcessQueryAsync(QueryRequest request, CancellationToken cancellationToken = default)
    {
        var stopwatch = Stopwatch.StartNew();
        var response = new QueryResponse
        {
            Metadata = new QueryMetadata
            {
                // 如果没有提供会话 ID，生成一个新的
                SessionId = request.SessionId ?? Guid.NewGuid().ToString()
            }
        };

        // 【强制超时保护】即使外部没传 CancellationToken，也强制60秒超时
        using var timeoutCts = new CancellationTokenSource(TimeSpan.FromSeconds(60));
        using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutCts.Token);
        var effectiveToken = linkedCts.Token;

        try
        {
            _logger.LogInformation("📝 [步骤1] 开始处理查询: {Query}", request.Query);

            // 🔍 优先检查缓存
            _logger.LogDebug("📝 [步骤2] 检查缓存...");
            var cachedResponse = await _cacheService.GetAsync(request.Query, request.DatabaseName);
            if (cachedResponse != null)
            {
                _logger.LogInformation("⚡ 返回缓存结果");
                cachedResponse.Metadata.ExecutionTimeMs = stopwatch.ElapsedMilliseconds;
                return cachedResponse;
            }

            // 特殊处理：能力查询
            if (IsCapabilityQuery(request.Query))
            {
                response.Success = true;
                response.Summary = GetCapabilitiesSummary();
                response.Data = GetCapabilitiesData();
                response.Metadata.ExecutionTimeMs = stopwatch.ElapsedMilliseconds;
                return response;
            }

            // 特殊处理：普通对话（不需要查询数据库）
            if (IsCasualConversation(request.Query))
            {
                _logger.LogInformation("📝 [步骤3] 检测到普通对话，直接路由到大模型");
                var conversationResponse = await HandleCasualConversationAsync(request.Query, effectiveToken);

                if (conversationResponse != null)
                {
                    response.Success = true;
                    response.Summary = conversationResponse;
                    response.Data = null;
                    response.Metadata.ExecutionTimeMs = stopwatch.ElapsedMilliseconds;
                    return response;
                }
            }
            
            // 特殊处理：既不是闲聊也不是数据查询，直接拒绝
            if (!IsDataQuery(request.Query))
            {
                _logger.LogInformation("❌ 检测到非校园数据查询问题，返回不支持提示");
                response.Success = true; // 改为 true，因为这是正常响应
                response.Summary = "抱歉，我只能查询校园数据，暂不支持这类问题😅\n\n我可以帮你查询：\n• 📹 设备状态（如：哪些摄像头离线了）\n• 👥 人员进出（如：今天有多少人进校）\n• 🚗 车辆管理（如：当前在校的外来车辆）\n• 📚 图书馆访问（如：十月份图书馆进出情况）\n\n试试问我这些数据相关的问题吧！";
                response.Data = null;
                response.Metadata.ExecutionTimeMs = stopwatch.ElapsedMilliseconds;
                return response;
            }

            // Build context
            _logger.LogInformation("📝 [步骤4] 构建查询上下文");
            var context = BuildContext(request);

            // Get available tools
            _logger.LogInformation("📝 [步骤5] 获取可用工具列表");
            var availableTools = _promptManager.GetAvailableTools();

            // Process with retry logic
            _logger.LogInformation("📝 [步骤6] 开始处理查询（带重试机制）");
            var result = await ProcessWithRetryAsync(request.Query, context, availableTools, effectiveToken);
            
            _logger.LogInformation("📝 [步骤7] 查询处理完成，结果: {Success}", result.Success);
            
            if (result.Success)
            {
                response.Success = true;
                response.Summary = result.Summary;
                response.Data = result.Data;
                response.Metadata.ExecutedSql = result.ExecutedSql;
                response.Metadata.UsedTools = result.UsedTools;
                response.Metadata.RowCount = result.RowCount;
                
                // 增强功能：当数据量超过阈值时，自动生成导出链接和图表
                await EnhanceResponseWithExportAndChartAsync(response, result, request, effectiveToken);
                
                // 💾 保存到缓存（成功的查询结果）
                await _cacheService.SetAsync(request.Query, response, request.DatabaseName);
            }
            else
            {
                response.Success = false;
                response.Errors = result.Errors;
                response.Summary = "查询失败，请检查输入或稍后重试。";
            }
        }
        catch (OperationCanceledException)
        {
            _logger.LogError("查询处理超时（60秒），可能是 AI 服务或数据库响应缓慢");
            response.Success = false;
            response.Errors.Add("查询超时");
            response.Summary = "查询超时，请稍后重试或简化查询条件。";
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "处理查询时发生错误");
            response.Success = false;
            response.Errors.Add($"系统错误：{ex.Message}");
            response.Summary = "处理查询时发生系统错误。";
        }
        finally
        {
            response.Metadata.ExecutionTimeMs = stopwatch.ElapsedMilliseconds;
            _logger.LogInformation("查询处理完成，耗时: {Time}ms", response.Metadata.ExecutionTimeMs);
        }

        return response;
    }

    private string BuildContext(QueryRequest request)
    {
        var context = new List<string>();
        
        if (!string.IsNullOrEmpty(request.DatabaseName))
        {
            context.Add($"目标数据库：{request.DatabaseName}");
        }
        
        if (request.Context != null && request.Context.Any())
        {
            context.Add($"额外上下文：{JsonConvert.SerializeObject(request.Context)}");
        }
        
        return string.Join("\n", context);
    }

    /// <summary>
    /// 带重试机制的查询处理
    /// 当查询失败时，会尝试让 AI 重新理解并修正错误
    /// </summary>
    /// <param name="query">原始查询语句</param>
    /// <param name="context">查询上下文</param>
    /// <param name="availableTools">可用的工具列表</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>处理结果</returns>
    private async Task<ProcessResult> ProcessWithRetryAsync(
        string query, 
        string context, 
        List<ToolDefinition> availableTools,
        CancellationToken cancellationToken)
    {
        var errors = new List<string>();
        string? lastAttempt = null;

        // 循环重试，最多重试 MaxRetryAttempts 次
        for (int attempt = 1; attempt <= MaxRetryAttempts; attempt++)
        {
            try
            {
                _logger.LogDebug("Processing query attempt {Attempt}/{Max}", attempt, MaxRetryAttempts);

                // Build prompt
                var prompt = attempt == 1
                    ? BuildInitialPrompt(query, context, availableTools)
                    : BuildRetryPrompt(query, errors.Last(), lastAttempt);
                    
                _logger.LogDebug("Sending prompt to model: {Prompt}", prompt);

                // Get model response with timeout protection
                _logger.LogInformation("📝 [AI调用] 开始调用大模型...");
                var modelResponse = await GetModelResponseWithTimeoutAsync(prompt, cancellationToken);
                
                if (modelResponse != null)
                {
                    _logger.LogInformation("📝 [AI调用] 大模型响应成功");
                }
                else
                {
                    _logger.LogWarning("📝 [AI调用] 大模型响应超时或失败");
                }

                if (modelResponse == null)
                {
                    // AI 调用超时，返回友好错误
                    return new ProcessResult
                    {
                        Success = false,
                        Summary = "抱歉，查询处理超时。请简化您的问题或稍后再试。",
                        Errors = new List<string> { "AI 模型响应超时" }
                    };
                }

                _logger.LogDebug("Received model response: {@Response}", modelResponse);
                
                // 根据模型返回的类型进行处理
                if (modelResponse.DirectAnswer != null)
                {
                    // 模型直接给出了答案，不需要执行工具
                    return new ProcessResult
                    {
                        Success = true,
                        Summary = modelResponse.DirectAnswer,
                        Data = null
                    };
                }
                
                if (modelResponse.Action != null)
                {
                    // 模型返回了工具调用指令，执行相应的工具
                    var toolResult = await _toolExecutor.ExecuteToolAsync(modelResponse.Action, cancellationToken);
                    
                    if (toolResult.Success)
                    {
                        // Generate summary based on tool result
                        var summary = await GenerateSummaryAsync(query, toolResult, cancellationToken);
                        
                        return new ProcessResult
                        {
                            Success = true,
                            Summary = summary,
                            Data = toolResult.Data,
                            UsedTools = new List<string> { modelResponse.Action.Tool },
                            ExecutedSql = toolResult.Metadata.ContainsKey("executedSql") 
                                ? toolResult.Metadata["executedSql"].ToString() 
                                : null,
                            RowCount = toolResult.Metadata.ContainsKey("rowCount") 
                                ? Convert.ToInt32(toolResult.Metadata["rowCount"]) 
                                : null
                        };
                    }
                    else
                    {
                        errors.AddRange(toolResult.Errors);
                        lastAttempt = JsonConvert.SerializeObject(modelResponse.Action);
                    }
                }
                else
                {
                    errors.Add("模型未返回有效的响应格式");
                }
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Error in attempt {Attempt}", attempt);
                errors.Add($"处理错误：{ex.Message}");
            }
        }

        return new ProcessResult
        {
            Success = false,
            Errors = errors
        };
    }

    private string BuildInitialPrompt(string query, string context, List<ToolDefinition> availableTools)
    {
        return _promptManager.BuildQueryPrompt(query, availableTools, context);
    }

    private string BuildRetryPrompt(string query, string lastError, string? lastAttempt)
    {
        return _promptManager.BuildErrorCorrectionPrompt(query, lastError, lastAttempt);
    }

    private async Task<string> GenerateSummaryAsync(string query, ToolResult toolResult, CancellationToken cancellationToken)
    {
        try
        {
            // 提取查询的时间范围等参数信息
            var queryContext = ExtractQueryContext(toolResult);
            
            var prompt = $@"基于以下查询和结果，生成一个简洁的中文摘要：

原始查询：{query}

{queryContext}

执行结果：
{JsonConvert.SerializeObject(toolResult.Data, Formatting.Indented)}

重要提示：
1. 如果查询条件中包含时间范围，请使用查询条件中的时间范围，不要从数据中推断时间
2. 简要说明查询结果的关键信息
3. 不要包含技术细节（如SQL、表名等）
4. 保持简洁（1-2句话）";

            using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
            cts.CancelAfter(TimeSpan.FromSeconds(10)); // 摘要生成最多10秒

            var response = await _qwenClient.GetStructuredResponseAsync(prompt, cts.Token);
            return response.DirectAnswer ?? "查询已完成，请查看详细数据。";
        }
        catch (OperationCanceledException)
        {
            _logger.LogWarning("Summary generation timeout");
            return "查询已完成，请查看详细数据。";
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "Failed to generate summary");
            return "查询已完成，请查看详细数据。";
        }
    }

    /// <summary>
    /// 带超时保护的 AI 模型调用
    /// </summary>
    private async Task<ModelResponse?> GetModelResponseWithTimeoutAsync(string prompt, CancellationToken cancellationToken)
    {
        var startTime = DateTime.UtcNow;
        try
        {
            using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
            cts.CancelAfter(TimeSpan.FromSeconds(30)); // AI 调用最多30秒

            _logger.LogInformation("⏱️ AI调用开始，超时限制: 30秒");
            
            var result = await _qwenClient.GetStructuredResponseAsync(prompt, cts.Token);
            
            var elapsed = (DateTime.UtcNow - startTime).TotalSeconds;
            _logger.LogInformation("✅ AI调用成功，耗时: {Elapsed:F2}秒", elapsed);
            
            return result;
        }
        catch (OperationCanceledException)
        {
            var elapsed = (DateTime.UtcNow - startTime).TotalSeconds;
            _logger.LogWarning("⏱️ AI调用超时，已等待: {Elapsed:F2}秒", elapsed);
            return null;
        }
        catch (Exception ex)
        {
            var elapsed = (DateTime.UtcNow - startTime).TotalSeconds;
            _logger.LogError(ex, "❌ AI调用失败，已等待: {Elapsed:F2}秒", elapsed);
            return null;
        }
    }

    /// <summary>
    /// 判断是否是能力查询
    /// </summary>
    private bool IsCapabilityQuery(string query)
    {
        var lowerQuery = query.ToLower().Trim();
        var keywords = new[] {
            "你能", "你可以", "能做什么", "能查询什么", "有什么功能", "支持什么",
            "能查什么", "可以查什么", "有哪些功能", "查询功能", "帮助", "help",
            "查什么数据", "什么数据", "有什么数据", "能力", "功能列表"
        };

        return keywords.Any(k => lowerQuery.Contains(k));
    }

    /// <summary>
    /// 获取系统能力摘要
    /// </summary>
    private string GetCapabilitiesSummary()
    {
        return @"我是智慧校园 AI 查询助手，可以帮助您查询以下数据：

📊 **设备管理**（10项）
• 设备在线/离线状态查询
• 设备故障统计和排名
• 告警记录查询

👥 **人员管理**（10项）
• 人员进出记录查询
• 在校人数统计
• 黑名单活动查询
• 部门员工信息查询

🚗 **车辆管理**（10项）
• 访客车辆查询
• 车辆进出记录
• 超速/违规车辆查询
• 白名单车辆管理

📝 **查询示例**
• ""哪些摄像头离线了？""
• ""今天有多少人进校？""
• ""现在有哪些外来车辆在校？""
• ""查看设备统计信息""
• ""昨天反复进出宿舍的学生""

💡 **提示**：直接用自然语言提问即可，我会自动理解并查询相关数据！";
    }

    /// <summary>
    /// 获取系统能力详细数据
    /// </summary>
    private object GetCapabilitiesData()
    {
        return new
        {
            categories = new[]
            {
                new
                {
                    name = "设备管理",
                    count = 10,
                    features = new[]
                    {
                        "设备在线/离线状态查询",
                        "设备故障统计",
                        "设备故障排名",
                        "告警记录查询",
                        "按区域查询设备",
                        "按类型查询设备",
                        "历史故障查询",
                        "离线时长统计",
                        "报警处理状态",
                        "设备统计概览"
                    }
                },
                new
                {
                    name = "人员管理",
                    count = 10,
                    features = new[]
                    {
                        "人员进出记录",
                        "闸机通行记录",
                        "在校人数统计",
                        "进校人数统计",
                        "黑名单活动查询",
                        "部门员工查询",
                        "异常时段人员",
                        "反复进出统计",
                        "个人通行记录",
                        "部门人数统计"
                    }
                },
                new
                {
                    name = "车辆管理",
                    count = 10,
                    features = new[]
                    {
                        "访客车辆查询",
                        "车辆进出记录",
                        "在校车辆统计",
                        "超速车辆查询",
                        "长时间停留车辆",
                        "白名单车辆",
                        "车主信息查询",
                        "电动车记录",
                        "夜间进校车辆",
                        "车辆进出统计"
                    }
                }
            },
            examples = new[]
            {
                new { query = "哪些摄像头离线了？", category = "设备管理" },
                new { query = "今天有多少设备报警？", category = "设备管理" },
                new { query = "今天进校了多少人？", category = "人员管理" },
                new { query = "昨晚10点后谁进了图书馆？", category = "人员管理" },
                new { query = "现在有哪些外来车辆在校？", category = "车辆管理" },
                new { query = "今天有车辆超速吗？", category = "车辆管理" }
            },
            totalFeatures = 30,
            supportedDatabases = new[] { "MySQL", "PostgreSQL", "SQL Server" },
            responseTime = "通常 1-3 秒",
            language = "中文自然语言"
        };
    }

    /// <summary>
    /// 判断是否是数据查询问题（需要同时满足：查询意图 + 校园相关主题）
    /// </summary>
    private bool IsDataQuery(string query)
    {
        var lowerQuery = query.ToLower().Trim();

        // 【关键改进】明确不是数据查询的黑名单（即使包含"今天"等词也不是）
        var nonDataQueryPatterns = new[] {
            "推荐", "建议", "怎么样", "好不好", "如何", "为什么", "什么意思",
            "菜", "饭", "吃", "喝", "买", "购物", "旅游", "电影", "音乐", "游戏",
            "学习方法", "怎么学", "教我", "告诉我怎么", "应该怎么",
            "新闻", "股票", "天气", "地址", "路线", "导航"
        };
        
        if (nonDataQueryPatterns.Any(k => lowerQuery.Contains(k)))
        {
            _logger.LogInformation("检测到非校园数据相关内容，不是数据查询");
            return false;
        }

        // 必须同时包含：查询意图词 + 校园主题词
        var queryIntentKeywords = new[] {
            "查询", "查看", "统计", "列出", "显示", "有多少", "有哪些",
            "什么时候", "谁", "哪个", "哪些"
        };
        
        var campusTopicKeywords = new[] {
            "设备", "摄像头", "闸机", "门禁", "监控",
            "人员", "学生", "老师", "员工", "访客", "进出", "进校", "出校",
            "车辆", "车牌", "外来车", "停车", "超速",
            "告警", "报警", "故障", "离线", "在线", "异常",
            "黑名单", "白名单", "部门", "区域",
            "图书馆", "宿舍", "教室", "食堂", "办公区",
            "记录", "数据", "明细"
        };

        var hasQueryIntent = queryIntentKeywords.Any(k => lowerQuery.Contains(k));
        var hasCampusTopic = campusTopicKeywords.Any(k => lowerQuery.Contains(k));
        
        // 必须同时满足才是数据查询
        if (hasQueryIntent && hasCampusTopic)
        {
            _logger.LogInformation("检测到查询意图 + 校园主题，判定为数据查询");
            return true;
        }
        
        // 或者：包含强烈的校园数据特征词（即使没有明确的查询词）
        var strongCampusKeywords = new[] {
            "离线摄像头", "故障设备", "在校人数", "外来车辆", "报警统计",
            "进出记录", "闸机记录", "通行记录", "访问记录"
        };
        
        if (strongCampusKeywords.Any(k => lowerQuery.Contains(k)))
        {
            _logger.LogInformation("检测到强烈的校园数据特征，判定为数据查询");
            return true;
        }

        _logger.LogInformation("未同时满足查询意图和校园主题，不是数据查询");
        return false;
    }

    /// <summary>
    /// 判断是否是普通对话（不需要查询数据库）
    /// 策略：优先检查明确的闲聊模式，避免被数据查询关键词误判
    /// </summary>
    private bool IsCasualConversation(string query)
    {
        var lowerQuery = query.ToLower().Trim();

        // 【优先级1】明确的问候语（完全匹配或开头匹配）
        var greetings = new[] { "你好", "您好", "hi", "hello", "嗨", "早上好", "下午好", "晚上好", "早", "哈喽" };
        if (greetings.Any(g => lowerQuery == g || lowerQuery.StartsWith(g)))
        {
            _logger.LogInformation("✅ 检测到问候语，使用普通对话模式");
            return true;
        }

        // 【优先级2】明确的闲聊模式（这些一定是闲聊，即使包含数据查询关键词）
        var casualPatterns = new[] {
            // 自我介绍类
            "你是谁", "你是什么", "介绍一下你", "你叫什么", "你的名字", "什么模型", "你会什么",
            "你能做什么", "你的功能", "怎么用你", "使用方法", "帮助文档",
            
            // 非数据查询的生活类（即使包含"推荐"、"今天"等词）
            "推荐", "建议", "天气", "新闻", "笑话", "聊天", "故事",
            "菜", "饭", "吃的", "喝的", "美食", "餐厅", "电影", "音乐", "游戏",
            "旅游", "景点", "路线", "学习方法", "怎么学",
            
            // 礼貌用语
            "谢谢你", "感谢", "再见", "拜拜", "bye", "拜了", "88",
            
            // 评价类
            "不错啊", "很好", "厉害了", "牛啊", "棒", "真赞",
            
            // 测试类
            "测试一下", "试试看", "试一下", "能听到吗", "在吗", "在不在", "听得到吗"
        };
        
        // 完全匹配或包含匹配
        if (casualPatterns.Any(p => lowerQuery == p || lowerQuery.Contains(p)))
        {
            _logger.LogInformation("✅ 检测到明确的闲聊模式（{Pattern}），使用普通对话", 
                casualPatterns.FirstOrDefault(p => lowerQuery.Contains(p)));
            return true;
        }

        // 【优先级3】简短问句（<=10字且以问号结尾，很可能是闲聊）
        if ((query.EndsWith("?") || query.EndsWith("？")) && query.Length <= 10)
        {
            _logger.LogInformation("✅ 检测到简短问句，使用普通对话");
            return true;
        }

        // 【优先级4】检查是否是数据查询
        // 注意：只有前面都不匹配才检查这个
        if (IsDataQuery(query))
        {
            _logger.LogInformation("❌ 检测到数据查询关键词，不是闲聊");
            return false;
        }

        // 【默认】都不是，返回 false（进入拒绝模式）
        _logger.LogInformation("❓ 未识别类型，进入拒绝模式");
        return false;
    }

    /// <summary>
    /// 处理普通对话，直接调用 AI 不使用工具（纯对话模式，不带查询助手角色）
    /// </summary>
    private async Task<string?> HandleCasualConversationAsync(string query, CancellationToken cancellationToken)
    {
        try
        {
            // 针对常见问题提供预设回复（仅限高频问题）
            var lowerQuery = query.ToLower().Trim();
            
            // 问候语（最高频）
            if (lowerQuery == "你好" || lowerQuery == "您好" || lowerQuery == "hi" || lowerQuery == "hello")
            {
                return "你好！我是智慧校园 AI 助手😊\n\n我可以帮你查询：\n• 📹 设备状态（如：哪些摄像头离线了）\n• 👥 人员进出（如：今天有多少人进校）\n• 🚗 车辆管理（如：当前在校的外来车辆）\n• 📚 图书馆访问（如：十月份图书馆进出情况）";
            }
            
            // 简单的自我介绍
            if (lowerQuery == "你是谁" || lowerQuery == "你是什么")
            {
                return "我是智慧校园 AI 助手😊 专门负责查询校园数据，有什么可以帮你的吗？";
            }
            
            // 礼貌用语
            if (lowerQuery == "谢谢" || lowerQuery == "感谢")
            {
                return "不客气😊";
            }
            
            if (lowerQuery == "再见" || lowerQuery == "拜拜" || lowerQuery == "bye")
            {
                return "再见😊";
            }
            
            // 【其他所有闲聊】让大模型自由发挥，不限制回答内容
            var prompt = $@"你是 Qwen，一个友好的 AI 助手。请用自然、轻松的语气回答用户的问题。

用户问：{query}

回答要求：
1. 尽力回答用户的问题，发挥你的常识和创造力
2. 如果确实无法回答（如查询实时天气、股票等），可以礼貌说明
3. 保持友好、幽默的语气
4. 回复简洁（2-3句话）
5. 用中文回复";

            using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
            cts.CancelAfter(TimeSpan.FromSeconds(15)); // 普通对话最多15秒

            var response = await _qwenClient.GetStructuredResponseAsync(prompt, cts.Token);
            
            // 如果大模型返回了内容，使用它的回答
            if (!string.IsNullOrWhiteSpace(response?.DirectAnswer))
            {
                return response.DirectAnswer;
            }
            
            // 兜底回复
            return "你好！有什么可以帮你的吗？😊";
        }
        catch (OperationCanceledException)
        {
            _logger.LogWarning("普通对话 AI 调用超时");
            return "抱歉，响应超时了。有什么可以帮你的吗？😊";
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "普通对话处理失败");
            return "你好！我可以帮你查询校园相关数据，比如设备状态、人员进出、车辆管理等😊";
        }
    }
    
    /// <summary>
    /// 从工具结果中提取查询上下文信息（如时间范围、查询条件等）
    /// </summary>
    private string ExtractQueryContext(ToolResult toolResult)
    {
        var contextLines = new List<string>();
        
        if (toolResult.Metadata.ContainsKey("executedSql"))
        {
            var sql = toolResult.Metadata["executedSql"]?.ToString() ?? "";
            
            // 提取时间范围
            var timeRangeMatch = System.Text.RegularExpressions.Regex.Match(
                sql, 
                @"InDt >= '([^']+)'.*?InDt <= '([^']+)'",
                System.Text.RegularExpressions.RegexOptions.Singleline
            );
            
            if (timeRangeMatch.Success)
            {
                var startTime = timeRangeMatch.Groups[1].Value;
                var endTime = timeRangeMatch.Groups[2].Value;
                contextLines.Add($"查询时间范围：{startTime} 至 {endTime}");
            }
            
            // 提取其他常见条件
            if (sql.Contains("未出场") || sql.Contains("IS NULL"))
            {
                contextLines.Add("筛选条件：未出场车辆");
            }
            
            if (sql.Contains("访客") || sql.Contains("CarCusName IS NULL"))
            {
                contextLines.Add("筛选条件：访客车辆（非包月用户）");
            }
            
            if (sql.Contains("OnLineStatus = 1"))
            {
                contextLines.Add("筛选条件：离线设备");
            }
            else if (sql.Contains("OnLineStatus = 2"))
            {
                contextLines.Add("筛选条件：在线设备");
            }
        }
        
        if (contextLines.Count > 0)
        {
            return "查询条件：\n" + string.Join("\n", contextLines);
        }
        
        return "";
    }

    private class ProcessResult
    {
        public bool Success { get; set; }
        public string Summary { get; set; } = string.Empty;
        public object? Data { get; set; }
        public List<string> Errors { get; set; } = new();
        public List<string> UsedTools { get; set; } = new();
        public string? ExecutedSql { get; set; }
        public int? RowCount { get; set; }
    }
    
    /// <summary>
    /// 增强响应：添加导出链接和图表配置
    /// </summary>
    private async Task EnhanceResponseWithExportAndChartAsync(
        QueryResponse response, 
        ProcessResult result, 
        QueryRequest request,
        CancellationToken cancellationToken)
    {
        try
        {
            _logger.LogInformation("开始增强响应，数据类型：{DataType}", result.Data?.GetType().Name ?? "null");
            
            // 获取数据行数
            int rowCount = GetDataRowCount(result.Data);
            
            _logger.LogInformation("检测到数据行数：{RowCount}，阈值：{Threshold}", rowCount, ExportThreshold);
            
            // 当数据量超过阈值时，生成导出链接
            if (rowCount > ExportThreshold)
            {
                _logger.LogInformation("数据量({RowCount})超过阈值({Threshold})，生成导出链接", 
                    rowCount, ExportThreshold);
                    
                // 获取使用的工具名称
                var toolName = result.UsedTools.FirstOrDefault();
                if (!string.IsNullOrEmpty(toolName))
                {
                    var baseUrl = _configuration["BaseUrl"] ?? "http://localhost:5000";
                    
                    // 构建导出提示信息
                    response.Metadata.ExportLinks = new ExportLinks
                    {
                        ExcelUrl = $"{baseUrl}/api/export/tool",
                        CsvUrl = $"{baseUrl}/api/export/tool",
                        Message = $"💾 数据量较大({rowCount}行)，建议使用导出功能下载完整数据。请使用POST请求到上述URL，参数：{{\"toolName\":\"{toolName}\",\"parameters\":{{}},\"format\":\"excel\"}}"
                    };
                }
            }
            
            // 自动生成ECharts图表配置（只要有数据就尝试生成）
            if (result.Data != null)
            {
                _logger.LogInformation("为查询结果生成图表配置，数据量：{RowCount}", rowCount);
                
                try
                {
                    var chartResult = await _chartService.GenerateChartAsync(result.Data);
                    
                    // 只有生成成功的图表才添加到响应中
                    if (chartResult.ChartType != "none")
                    {
                        response.Metadata.ChartConfig = new ChartConfig
                        {
                            Type = chartResult.ChartType,
                            Config = chartResult.Config,
                            Description = chartResult.Summary
                        };
                        
                        _logger.LogInformation("✅ 图表配置生成成功，类型：{ChartType}", chartResult.ChartType);
                    }
                    else
                    {
                        _logger.LogInformation("ℹ️ 不适合生成图表：{Reason}", chartResult.Summary);
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogWarning(ex, "生成图表配置失败，但不影响主查询结果");
                    // 图表生成失败不影响主查询结果
                }
            }
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "增强响应时发生错误，但不影响主查询结果");
            // 增强功能失败不影响主查询结果
        }
    }
    
    /// <summary>
    /// 获取数据行数
    /// </summary>
    private int GetDataRowCount(object? data)
    {
        if (data == null) return 0;
        
        try
        {
            _logger.LogDebug("GetDataRowCount - 数据类型: {Type}", data.GetType().FullName);
            
            // 处理匿名对象（DatabaseExecutor返回的格式：{ columns, rows }）
            var dataType = data.GetType();
            var rowsProperty = dataType.GetProperty("rows");
            if (rowsProperty != null)
            {
                var rowsValue = rowsProperty.GetValue(data);
                if (rowsValue is System.Collections.IList rowsList)
                {
                    _logger.LogDebug("从 rows 属性获取到 {Count} 行数据", rowsList.Count);
                    return rowsList.Count;
                }
                if (rowsValue is System.Collections.IEnumerable rowsEnumerable && rowsValue is not string)
                {
                    var count = rowsEnumerable.Cast<object>().Count();
                    _logger.LogDebug("从 rows 可枚举对象获取到 {Count} 行数据", count);
                    return count;
                }
            }
            
            // 处理JsonElement类型
            if (data is JsonElement jsonElement)
            {
                if (jsonElement.ValueKind == JsonValueKind.Array)
                {
                    return jsonElement.GetArrayLength();
                }
                else if (jsonElement.ValueKind == JsonValueKind.Object)
                {
                    // 检查是否有columns和rows属性
                    if (jsonElement.TryGetProperty("rows", out var rows) && 
                        rows.ValueKind == JsonValueKind.Array)
                    {
                        return rows.GetArrayLength();
                    }
                    return 1;
                }
            }
            
            // 处理IEnumerable类型
            if (data is System.Collections.IEnumerable enumerable && data is not string)
            {
                var count = enumerable.Cast<object>().Count();
                _logger.LogDebug("从可枚举对象获取到 {Count} 行数据", count);
                return count;
            }
            
            _logger.LogDebug("数据被识别为单个对象");
            return 1; // 单个对象
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "获取数据行数时发生错误");
            return 0;
        }
    }
}
